package org.mx.service.server;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.mx.StringUtils;
import org.mx.service.server.jmx.ServletServer;
import org.mx.service.server.servlet.BaseHttpServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

/**
 * 基于Jetty的Servlet服务器工厂类
 *
 * @author : john.peng created on date : 2017/10/6
 */
public class ServletServerFactory extends HttpServerFactory {
	private static final Logger logger = LoggerFactory.getLogger(ServletServerFactory.class);

	private ServletServerConfigBean servletServerConfigBean;

	/**
	 * 构造函数
	 * 
	 * @param context                 Spring IoC上下文
	 * @param servletServerConfigBean Servlet服务器配置信息
	 * @param servletServerMXBean	Servlet服务器MXBean对象
	 */
	public ServletServerFactory(ApplicationContext context, ServletServerConfigBean servletServerConfigBean,
			ServletServer servletServerMXBean) {
		super(context, servletServerConfigBean, servletServerMXBean);
		this.servletServerConfigBean = servletServerConfigBean;
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see HttpServerFactory#getHandler()
	 */
	@Override
	@SuppressWarnings("unchecked")
	protected Handler getHandler() {
		String[] classesDefs = servletServerConfigBean.getServiceClasses();
		if (classesDefs == null || classesDefs.length <= 0) {
			if (logger.isWarnEnabled()) {
				logger.warn("You not define any servlet classes.");
			}
			return null;
		} else {
			ServletContextHandler contextHandler = new ServletContextHandler(1);
			Set<String> resourceNames = new HashSet<>();
			contextHandler.setContextPath("/");
			for (String classesDef : classesDefs) {
				if (!StringUtils.isBlank(classesDef)) {
					List<Class<?>> servletClasses = (List<Class<?>>) context.getBean(classesDef, List.class);
					if (!servletClasses.isEmpty()) {
						servletClasses.forEach((clazz) -> {
							resourceNames.add(clazz.getName());
							BaseHttpServlet servlet = (BaseHttpServlet) context.getBean(clazz);
							contextHandler.addServlet(new ServletHolder(servlet), servlet.getPath());
						});
					}
				}
			}
			if (super.httpServerMXBean != null) {
				((ServletServer) super.httpServerMXBean).setServletServerResources(resourceNames);
			}
			return contextHandler;
		}
	}
}
